package com.bigData.main.controller;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

import static com.bigData.main.controller.Const.HC_DIR_BASE;

@RestController
@RequestMapping("/hdfs")
public class HdfsUploadController {

    private final FileSystem fileSystem;

    @Autowired
    public HdfsUploadController(FileSystem fileSystem) {
        this.fileSystem = fileSystem;
    }

    // 原有上传方法
    @PostMapping("/upload")
    public ResponseEntity<?> uploadToHdfs(@RequestBody HdfsUploadRequest request) {
        Path hdfsPath = new Path(HC_DIR_BASE + request.getFilename());

        try (FSDataOutputStream outputStream = fileSystem.create(hdfsPath, true)) {
            byte[] contentBytes = request.getContent().getBytes(StandardCharsets.UTF_8);
            outputStream.write(contentBytes);

            FileStatus fileStatus = fileSystem.getFileStatus(hdfsPath);

            return ResponseEntity.ok(new HdfsUploadResponse(
                    hdfsPath.toString(),
                    fileStatus.getLen(),
                    "文件写入成功"
            ));

        } catch (IOException e) {
            return handleHdfsError(e, HC_DIR_BASE + request.getFilename());
        }
    }

    // 新增安全上传方法
    @PostMapping("/secure-upload")
    public ResponseEntity<?> secureUpload(
            @RequestHeader("X-Auth-Code") String code,
            @RequestParam("filename") String filename,
            @RequestBody byte[] content) {

        if (!"123456".equals(code)) {
            return ResponseEntity.status(403).body("无效对接码");
        }

        Path hdfsPath = new Path(HC_DIR_BASE + filename);
        try (FSDataOutputStream outputStream = fileSystem.create(hdfsPath, true)) {
            outputStream.write(content);

            FileStatus fileStatus = fileSystem.getFileStatus(hdfsPath);
            return ResponseEntity.ok(new HdfsUploadResponse(
                    hdfsPath.toString(),
                    fileStatus.getLen(),
                    "安全写入成功"));

        } catch (IOException e) {
            return handleHdfsError(e, HC_DIR_BASE + filename);
        }
    }

    // 原有直接上传方法
    @PostMapping("/direct-upload")
    public ResponseEntity<?> directUploadToHdfs(@RequestParam("file") MultipartFile file) {
        try {
            Path hdfsPath = new Path(HC_DIR_BASE + file.getOriginalFilename());
            try (FSDataOutputStream outputStream = fileSystem.create(hdfsPath, true)) {
                outputStream.write(file.getBytes());
                return ResponseEntity.ok("文件已直接上传至HDFS");
            }
        } catch (IOException e) {
            return handleHdfsError(e, HC_DIR_BASE + file.getOriginalFilename());
        }
    }

    // 统一异常处理方法
    private ResponseEntity<HdfsErrorResponse> handleHdfsError(Exception e, String targetPath) {
        String errorMessage = "HDFS操作失败: " + e.getMessage();
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new HdfsErrorResponse(
                        errorMessage,
                        e.getClass().getSimpleName(),
                        targetPath
                ));
    }

    // DTO 类
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class HdfsUploadRequest {
        private String content;
        private String filename;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class HdfsUploadResponse {
        private String path;
        private long fileSize;
        private String message;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class HdfsErrorResponse {
        private String message;
        private String errorType;
        private String targetPath;
    }
}